﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;

namespace ArticleWeb
{
    public static class ResultExtension
    {
        //JsonResult Json(object data);
        static MethodInfo JsonMethodP1;
        //JsonResult Json(object data, string contentType);
        static MethodInfo JsonMethodP2;
        //JsonResult Json(object data, JsonRequestBehavior behavior);
        static MethodInfo JsonMethodP2A;
        //JsonResult Json(object data, string contentType, Encoding contentEncoding);
        static MethodInfo JsonMethodP3;
        //JsonResult Json(object data, string contentType, JsonRequestBehavior behavior);
        static MethodInfo JsonMethodP3A;
        //JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior);
        static MethodInfo JsonMethodP4;
        static ResultExtension()
        {
            var methods = typeof(Controller).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.Name == "Json");
            foreach (var item in methods)
            {
                var p = item.GetParameters();
                var pLen = p.Length;
                if (pLen == 1)
                {
                    JsonMethodP1 = item;
                }
                else if (pLen == 2)
                {
                    if (p.Any(x => x.ParameterType == typeof(JsonRequestBehavior)))
                    {
                        JsonMethodP2A = item;
                    }
                    else
                    {
                        JsonMethodP2 = item;
                    }
                }
                else if (pLen == 3)
                {
                    if (p.Any(x => x.ParameterType == typeof(JsonRequestBehavior)))
                    {
                        JsonMethodP3A = item;
                    }
                    else
                    {
                        JsonMethodP3 = item;
                    }
                }
                else if (pLen == 4)
                {
                    JsonMethodP4 = item;
                }
            }
        }

        /// <summary>
        /// 返回一个请求验证token，该token用于一个带有[ValidateAntiForgeryTokenAttribute]特性的接口
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public static JsonResult JsonToken(this Controller controller)
        {
            var token = AntiForgery.GetHtml().ToHtmlString();
            //<input name="__RequestVerificationToken" type="hidden" value="(.+)" />
            var match = new Regex("<input name=\"__RequestVerificationToken\" type=\"hidden\" value=\"(.+)\" />").Match(token);
            return controller.JsonEx(200, match.Groups[1].Value);
        }

        /// <summary>
        /// 返回一个格式为{ code = code, msg = msg }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="code"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static JsonResult JsonEx(this Controller controller, int code, string msg)
        {
            return controller.Json(new { code = code, msg = msg }, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 返回一个格式为{ code = 400, msg = "错误请求" }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public static JsonResult JsonBadRequest(this Controller controller)
        {
            return controller.Json(new { code = 400, msg = "错误请求" });
        }

        /// <summary>
        /// 返回一个格式为{ code = 10010, msg = "同名资源已存在" }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public static JsonResult JsonDuplicate(this Controller controller)
        {
            return controller.Json(new { code = 10010, msg = "同名资源已存在" });
        }

        /// <summary>
        /// 返回一个格式为{ code = 404, msg = "无效资源" }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public static JsonResult JsonNotFound(this Controller controller)
        {
            return controller.Json(new { code = 404, msg = "无效资源" });
        }

        /// <summary>
        /// 返回一个格式为{ code = 200, msg = "操作成功" }的对象
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public static JsonResult JsonOk(this Controller controller)
        {
            return controller.Json(new { code = 200, msg = "操作成功" });
        }

        /// <summary>
        /// 返回一个格式为{ code = 200, msg = "操作成功", data = data }的对象
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static JsonResult JsonOk(this Controller controller, object data, JsonRequestBehavior jrb = JsonRequestBehavior.DenyGet)
        {
            return controller.Json(new { code = 200, msg = "操作成功", data = data }, jrb);
        }

        /// <summary>
        /// 返回一个格式为{ code = 200, msg = msg }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static JsonResult JsonOk(this Controller controller, string msg)
        {
            return controller.Json(new { code = 200, msg = msg });
        }

        /// <summary>
        /// 返回一个格式为{ code = 200, msg = msg, data = data }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static JsonResult JsonOk(this Controller controller, object data, string msg)
        {
            return controller.Json(new { code = 200, msg = msg, data = data });
        }

        /// <summary>
        /// 返回一个格式为{ code = 500, msg = msg }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static JsonResult JsonError(this Controller controller, string msg)
        {
            return controller.Json(new { code = 500, msg = msg });
        }

        /// <summary>
        /// 返回一个格式为{ code = 500, msg = msg, data = data }的JSON对象
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="msg"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static JsonResult JsonError(this Controller controller, string msg, object data)
        {
            return controller.Json(new { code = 500, msg = msg, data = data });
        }

        #region Controller Internal Calls Wrapper
        private static JsonResult Json(this Controller controller, object data)
        {
            object returnVal = null;
            try
            {
                returnVal = JsonMethodP1.Invoke(controller, new object[] { data });
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
            return returnVal as JsonResult;
        }
        private static JsonResult Json(this Controller controller, object data, string contentType)
        {
            object returnVal = null;
            try
            {
                returnVal = JsonMethodP2.Invoke(controller, new object[] { data, contentType });
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
            return returnVal as JsonResult;
        }
        private static JsonResult Json(this Controller controller, object data, JsonRequestBehavior behavior)
        {
            object returnVal = null;
            try
            {
                returnVal = JsonMethodP2A.Invoke(controller, new object[] { data, behavior });
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
            return returnVal as JsonResult;
        }
        private static JsonResult Json(this Controller controller, object data, string contentType, Encoding contentEncoding)
        {
            object returnVal = null;
            try
            {
                returnVal = JsonMethodP3.Invoke(controller, new object[] { data, contentType, contentEncoding });
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
            return returnVal as JsonResult;
        }
        private static JsonResult Json(this Controller controller, object data, string contentType, JsonRequestBehavior behavior)
        {
            object returnVal = null;
            try
            {
                returnVal = JsonMethodP3A.Invoke(controller, new object[] { data, contentType, behavior });
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
            return returnVal as JsonResult;
        }
        private static JsonResult Json(this Controller controller, object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
        {
            object returnVal = null;
            try
            {
                returnVal = JsonMethodP4.Invoke(controller, new object[] { data, contentType, contentEncoding, behavior });
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
            return returnVal as JsonResult;
        }
        #endregion
    }
}